/*
  * @file Segment.cpp
  * @author Thibault Merle et Guillaume Poussel
  */
#include <iostream>

#include "base/Vector.h"
#include "base/Segment.h"
#include "base/Point.h"
#include "base/geometry.h"


using namespace std;

ostream& operator<<(ostream& os, const Segment& seg) {
    return os << '[' << *(seg._pt1) << " ; " << *(seg._pt2) << ']';
}

bool Segment::contains(const Point* pt) const {
    Vector vab(this);
    Vector vap(_pt1, pt);
    if (cross_product(&vab, &vap) != 0) {
        return false;
    }
    // P sur la droite (AB)
    if (_pt1->x() == _pt2->x()) {
        p_type yMin = 0, yMax = 0;
        if (_pt1->y() < _pt2->y()) {
            yMin = _pt1->y();
            yMax = _pt2->y();
        } else {
            yMin = _pt2->y();
            yMax = _pt1->y();
        }
        return yMin <= pt->y() &&  pt->y() <= yMax;
    } else {
        p_type xMin = 0, xMax = 0;
        if (_pt1->x() < _pt2->x()) {
            xMin = _pt1->x();
            xMax = _pt2->x();
        } else {
            xMin = _pt2->x();
            xMax = _pt1->x();
        }
        return xMin <= pt->x() &&  pt->x() <= xMax;
    }
}

bool Segment::intersects_radius(const Point* p) const {
    Vector ap(_pt1, p);
    Vector vab(this);
    if (_pt1->y() <= _pt2->y()) { //yA <= yB
        if (!(p->y() >= _pt1->y() &&
              p->y() <= _pt2->y())) {
            return false;
        }
    } else { // yB < yA
        if (!(p->y() <= _pt1->y() &&
              p->y() >= _pt2->y())) {
            return false;
        }
    }
    c_prod_type cr_prod = cross_product(&vab, &ap);
    return cr_prod == 0 ||
            !((cr_prod >= 0 && _pt1->y() >= p->y()) ||
              (cr_prod <= 0 && _pt1->y() <= p->y()));
}

bool Segment::intersect_segment(const Segment* segment) const {
    const Point* A = this->pt1(), *B = this->pt2(), *C = segment->pt1(), *D = segment->pt2();
    Vector AB(this);
    Vector AC(A,C);
    Vector AD(A,D);

    c_prod_type result1 = cross_product(&AB,&AC);
    c_prod_type result2 = cross_product(&AB,&AD);

    if(!((result1 <= 0 && result2 >= 0) || (result1 >= 0 && result2 <= 0))) {
        return false;
    }

    Vector CD(segment);
    Vector CA(C,A);
    Vector CB(C,B);
    c_prod_type result3 = cross_product(&CD,&CA);
    c_prod_type result4 = cross_product(&CD,&CB);

    return (result3 <= 0 && result4 >= 0) || (result3 >= 0 && result4 <= 0);
}

